﻿using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Data;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Security;
using Nop.Core.Domain.Stores;
using Nop.Core.Domain.WindAlert;
using Nop.Services.Events;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Nop.Services.WindAlert
{
    /// <summary>
    /// Spot service
    /// </summary>
    public partial class AlertService : IAlertService
    {
        #region Fields

        private readonly IRepository<SpotsGroup> _spotsGroupRepository;
        private readonly IRepository<Spot> _spotRepository;
        private readonly IRepository<Alert> _alertRepository;
        private readonly IRepository<Customer> _customerRepository;
        private readonly IWorkContext _workContext;
        private readonly IEventPublisher _eventPublisher;
        #endregion

        #region Ctor

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="cacheManager">Cache manager</param>
        /// <param name="spotRepository">Live Spot repository</param>
        public AlertService(
            IRepository<SpotsGroup> spotsGroupRepository,
            IRepository<Spot> spotRepository,
            IRepository<Alert> alertRepository,
            IRepository<Customer> customerRepository,
            IWorkContext workContext,
            IStoreContext storeContext,
            IEventPublisher eventPublisher)
        {
            this._spotRepository = spotRepository;
            this._spotsGroupRepository = spotsGroupRepository;
            this._alertRepository = alertRepository;
            this._customerRepository = customerRepository;
            this._workContext = workContext;
            _eventPublisher = eventPublisher;
        }
        #endregion

        #region Methods

        /// <summary>
        /// Deletes a spot group
        /// </summary>
        /// <param name="spot">SpotsGroup</param>
        public virtual void DeleteSpotsGroup(SpotsGroup spotsGroup)
        {
            if (spotsGroup == null)
                throw new ArgumentNullException("spotGroup");

            _spotsGroupRepository.Delete(spotsGroup);

            //event notification
            _eventPublisher.EntityDeleted(spotsGroup);
        }


        /// <summary>
        /// Gets all spotsGroup
        /// </summary>
        /// <param name="spotId">SpotsGroup Id</param>
        /// <returns>SpotsGroup collection</returns>
        public virtual IList<SpotsGroup> GetAllSpotsGroups(int alertOptionId = 0)
        {

                var query = from sg in _spotsGroupRepository.Table
                            orderby sg.DisplayOrder
                            where (sg.Published)  
                            select sg;
                if (alertOptionId > 0)
                {
                    query = query.Where(sg => sg.AlertOptionId  == alertOptionId);
                }

                var spotsGroup = query.ToList();
                return spotsGroup;

        }

        /// <summary>
        /// Gets all spotsGroups
        /// </summary>
        /// <param name="pageIndex">Page index</param>
        /// <param name="pageSize">Page size</param>
        /// <returns>SpotsGroup</returns>
        public virtual IPagedList<SpotsGroup> GetAllSpotsGroups(int pageIndex, int pageSize, int alertOptionId = 0)
        {
            var spotsGroups = GetAllSpotsGroups(alertOptionId);
            return new PagedList<SpotsGroup>(spotsGroups, pageIndex, pageSize);
        }

        /// <summary>
        /// Gets a spotsGroup
        /// </summary>
        /// <param name="spotsGroupId">SpotsGroup identifier</param>
        /// <returns>SpotsGroup</returns>
        public virtual SpotsGroup GetSpotsGroupById(int spotsGroupId)
        {
            if (spotsGroupId == 0)
                return null;

                var spot = _spotsGroupRepository.GetById(spotsGroupId);
                return spot;
        }

        /// <summary>
        /// Inserts a spotsGroup
        /// </summary>
        /// <param name="spotsGroup">SpotsGroup</param>
        public virtual void InsertSpotsGroup(SpotsGroup spotsGroup)
        {
            if (spotsGroup == null)
                throw new ArgumentNullException("spotsGroup");

            _spotsGroupRepository.Insert(spotsGroup);

        }

        /// <summary>
        /// Updates the spotsGroup
        /// </summary>
        /// <param name="spotsGroup">SpotsGroup</param>
        public virtual void UpdateSpotsGroup(SpotsGroup spotsGroup)
        {
            if (spotsGroup == null)
                throw new ArgumentNullException("spotsGroup");

            _spotsGroupRepository.Update(spotsGroup);

        }

        #region alerts

        /// <summary>
        /// Deletes a alert
        /// </summary>
        /// <param name="alert">alert</param>
        public virtual void DeleteAlert(Alert alert)
        {
            if (alert == null)
                throw new ArgumentNullException("alert");

            _alertRepository.Delete(alert);


            //event notification
            _eventPublisher.EntityDeleted(alert);
        }

        /// <summary>
        /// Gets alerts collection
        /// </summary>
        /// <param name="SpotsGroupId">SpotsGroup identifier</param>
        /// <param name="pageIndex">Page index</param>
        /// <param name="pageSize">Page size</param>
        /// <returns>SpotsGroup Customer mapping collection</returns>
        public virtual IPagedList<Alert> GetAlertsBySpotsGroupId(int spotsGroupId, int pageIndex, int pageSize)
        {
            if (spotsGroupId == 0)
                return new PagedList<Alert>(new List<Alert>(), pageIndex, pageSize);

                var query = from a in _alertRepository.Table
                            join c in _customerRepository.Table on a.CustomerId equals c.Id
                            where a.SpotsGroupId == spotsGroupId &&
                                  !c.Deleted &&
                                  (c.Active)
                            orderby a.Id
                            select a;

                var alerts = new PagedList<Alert>(query, pageIndex, pageSize);
                return alerts;
        }

    
        /// <summary>
        /// Gets a alert collection
        /// </summary>
        /// <param name="customerId">Product identifier</param>
        /// <returns> alerts collection</returns>
        public virtual IList<Alert> GetAlertsByCustomerId(int customerId)
        {
            if (customerId == 0)
                return new List<Alert>();

                var query = from a in _alertRepository.Table
                            join s in _spotsGroupRepository.Table on a.SpotsGroupId equals s.Id
                            where a.CustomerId == customerId &&
                                  (s.Published)
                            orderby a.Id
                            select a;

                var allAlerts = query.ToList();
                var result = new List<Alert>();

                //no filtering
                result.AddRange(allAlerts);
                return result;
        }

        /// <summary>
        /// Gets a Alert  
        /// </summary>
        /// <param name="AlertId">Alert identifier</param>
        /// <returns>Alert</returns>
        public virtual Alert GetAlertById(int alertId)
        {
            if (alertId == 0)
                return null;

            return _alertRepository.GetById(alertId);
        }

        /// <summary>
        /// Inserts Alert
        /// </summary>
        /// <param name="Alert">Alert</param>
        public virtual void InsertAlert(Alert alert)
        {
            if (alert == null)
                throw new ArgumentNullException("alert");

            _alertRepository.Insert(alert);

            //event notification
            _eventPublisher.EntityInserted(alert);
        }

        /// <summary>
        /// Updates the Alert  
        /// </summary>
        /// <param name="Alert">Alert</param>
        public virtual void UpdateAlert(Alert alert)
        {
            if (alert == null)
                throw new ArgumentNullException("alert");

            _alertRepository.Update(alert);

            //event notification
            _eventPublisher.EntityUpdated(alert);
        }

        /// <summary>
        /// Get chaeck existing record
        /// </summary>
        /// <returns>Alert</returns>
        public virtual Alert CheckIfAlertExists(Alert alert)
        {
            var query = from a in _alertRepository.Table
                        orderby a.Id
                        where a.SpotsGroupId == alert.SpotsGroupId && a.CustomerId == alert.CustomerId
                        select a;
            var results = query.FirstOrDefault();
            return results;
        }


        #endregion

        #endregion

    }
}
